package org.han.permission.service.impl;

import org.han.annotation.RonghuanetPermission;
import org.han.permission.domain.Permission;
import org.han.permission.mapper.PermissionMapper;
import org.han.permission.service.IPermissionScanService;
import org.han.util.ClassUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class PermissionScanServiceImpl implements IPermissionScanService {
    @Value("${hhang.permission.scanPackage}")
    private String scanPackage;//从配置文件中读取配置权限扫描包

    @Resource
    private PermissionMapper mapper;
    /**
     * 容器启动,权限扫描
     */
    @Transactional
    @Override
    public void scan() {
        //获取所有controller包下所有的类
        List<Class> classes = ClassUtils.getAllClassName(this.scanPackage);
        List<Permission> permissions = new ArrayList<>();
        // 循环所有的controller
        for (Class aClass : classes) {
            // 判断controller上是否有自定义注解
            RonghuanetPermission annotation = (RonghuanetPermission)aClass.getAnnotation(RonghuanetPermission.class);
            if(Objects.isNull(annotation)){
                // 为空说明没有自定义注解 直接跳过
                continue;
            }
            // 将类上面的注解也解析成一个Permission对象,作为方法权限对象的父亲
            Permission permission = new Permission();
            permission.setName(annotation.name());
            permission.setDescs(annotation.desc());
            // 区类的url
            RequestMapping annotation1 = (RequestMapping)aClass.getAnnotation(RequestMapping.class);
            if(Objects.nonNull(annotation1)){
                permission.setUrl(annotation1.value()[0]);
            }
            permission.setSn(aClass.getSimpleName());
            permissions.add(permission);
            // 如果有自定义注解,就说明这个类里面的方法需要权限才能访问
            // 获取这个类里面所有的方法(反射)
            Method[] methods = aClass.getMethods();
            for (Method method : methods) {
                //  判断方法上面有没有自定义注解
                RonghuanetPermission methodAnnotation = method.getAnnotation(RonghuanetPermission.class);
                if(Objects.isNull(methodAnnotation)){
                    //没有自定义注解直接跳过
                    continue;
                }
                // 如果有注解,就封装Permission对象,并存到数据库的t_permission表中
                Permission permission1 = new Permission();
                permission1.setName(methodAnnotation.name());
                permission1.setDescs(methodAnnotation.desc());
                // url 类上面的 url + 方法上面的url
                permission1.setUrl(getUrl(aClass,method));
                // su 类名:方法名
                permission1.setSn(aClass.getSimpleName() + ":" + method.getName());
                // 设置父权限对象
                permission1.setPname(permission);
                permissions.add(permission1);

                // 删除所有权限
                mapper.deleteAll();
                // 添加权限
                if(!CollectionUtils.isEmpty(permissions)){
                    for (Permission permission2 : permissions) {
                        mapper.insert(permission2);
                    }
                }
            }

        }
    }

    private String getUrl(Class aClass, Method method) {
        String url = "";
        // 获取类名的url
        RequestMapping annotation = (RequestMapping)aClass.getAnnotation(RequestMapping.class);
        if(Objects.nonNull(annotation)){
            url = annotation.value()[0];
        }
        // 获取方法的url
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if(Objects.nonNull(getMapping) && getMapping.value().length > 0){
            url = getMapping.value()[0];
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if(Objects.nonNull(postMapping) && postMapping.value().length > 0){
            url = postMapping.value()[0];
        }
        PutMapping putMapping= method.getAnnotation(PutMapping.class);
        if(Objects.nonNull(putMapping) && putMapping.value().length > 0){
            url = putMapping.value()[0];
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (Objects.nonNull(deleteMapping) && deleteMapping.value().length > 0){
            url = deleteMapping.value()[0];
        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if(Objects.nonNull(patchMapping) && patchMapping.value().length > 0){
            url = patchMapping.value()[0];
        }
        return url;
    }
}
